package homework;

import java.util.*;

/**
 * 成绩区间类，定义区间范围和对应等级
 */
class GradeRange {
    private final double min;
    private final double max;
    private final String level;

    public GradeRange(double min, double max, String level) {
        this.min = min;
        this.max = max;
        this.level = level;
    }

    public boolean inRange(double score) {
        return score >= min && score < max;
    }

    public String getLevel() {
        return level;
    }
}

/**
 * 性别枚举，限定性别只能为Male或Female
 */
enum Gender {
    MALE("男"),
    FEMALE("女");

    private final String label;

    Gender(String label) {
        this.label = label;
    }

    public String getLabel() {
        return label;
    }

    public static Gender fromString(String str) {
        for (Gender g : Gender.values()) {
            if (g.label.equals(str)) return g;
        }
        throw new IllegalArgumentException("无效的性别：" + str);
    }
}

/**
 * 课程枚举，可根据需要扩展
 */
enum Course {
    JAVA("Java"),
    ALGORITHM("算法"),
    MACHINE_LEARNING("机器学习"),
    DATA_MINING("数据挖掘");

    private final String label;

    Course(String label) {
        this.label = label;
    }

    public String getLabel() {
        return label;
    }

    public static Course fromString(String str) {
        for (Course c : Course.values()) {
            if (c.label.equals(str)) return c;
        }
        throw new IllegalArgumentException("无效的课程：" + str);
    }
}

/**
 * 成绩接口
 */
interface ScoreAble {
    String getGradeLevel();
}

/**
 * 抽象学生类，定义了基础信息和成绩等级判定通用逻辑
 */
abstract class Student implements ScoreAble {
    private final String ID;
    private final String name;
    private final Gender gender;
    private final Course course;
    private final double score;

    public Student(String ID, String name, String genderStr, String courseStr, double score) {
        if (ID == null || ID.isBlank()) throw new IllegalArgumentException("学号不能为空");
        if (name == null || name.isBlank()) throw new IllegalArgumentException("姓名不能为空");
        this.gender = Gender.fromString(genderStr);
        this.course = Course.fromString(courseStr);
        if (score < 0 || score > 100) throw new IllegalArgumentException("成绩必须在0~100之间");

        this.ID = ID;
        this.name = name;
        this.score = score;
    }

    public String getID() { return ID; }
    public String getName() { return name; }
    public Gender getGender() { return gender; }
    public Course getCourse() { return course; }
    public double getScore() { return score; }

    /**
     * 子类提供对应的成绩区间列表
     */
    protected abstract List<GradeRange> initGradeRanges();

    @Override
    public String getGradeLevel() {
        for (GradeRange range : initGradeRanges()) {
            if (range.inRange(score)) {
                return range.getLevel();
            }
        }
        return "不及格";  // 默认兜底
    }
}

/**
 * 本科生
 */
class Undergraduate extends Student {

    private static final List<GradeRange> UGRADE_RANGES = List.of(
            new GradeRange(80, 101, "优秀"),
            new GradeRange(70, 80, "良好"),
            new GradeRange(60, 70, "一般"),
            new GradeRange(50, 60, "及格"),
            new GradeRange(0, 50, "不及格")
    );

    public Undergraduate(String ID, String name, String gender, String course, double score) {
        super(ID, name, gender, course, score);
    }

    @Override
    protected List<GradeRange> initGradeRanges() {
        return UGRADE_RANGES;
    }
}

/**
 * 研究生
 */
class Postgraduate extends Student {

    private static final List<GradeRange> PGRADE_RANGES = List.of(
            new GradeRange(90, 101, "优秀"),
            new GradeRange(80, 90, "良好"),
            new GradeRange(70, 80, "一般"),
            new GradeRange(60, 70, "及格"),
            new GradeRange(0, 60, "不及格")
    );

    public Postgraduate(String ID, String name, String gender, String course, double score) {
        super(ID, name, gender, course, score);
    }

    @Override
    protected List<GradeRange> initGradeRanges() {
        return PGRADE_RANGES;
    }
}

/**
 * 主程序类
 */
public class Experiment7 {

    /**
     * 存储学生，使用Map防止学号重复
     */
    private final Map<String, Student> studentMap = new LinkedHashMap<>();


     // 添加学生，检查重复学号

    public void addStudent(Student s) {
        if (studentMap.containsKey(s.getID())) {
            throw new IllegalArgumentException("学号重复: " + s.getID());
        }
        studentMap.put(s.getID(), s);
    }

// 打印所有本科生成绩
    public void printUndergraduates() {
        System.out.println("本科生成绩等级：");
        for (Student s : studentMap.values()) {
            if (s instanceof Undergraduate) {
                printStudentInfo(s);
            }
        }
    }
//打印所有研究生成绩
    public void printPostgraduates() {
        System.out.println("研究生成绩等级：");
        for (Student s : studentMap.values()) {
            if (s instanceof Postgraduate) {
                printStudentInfo(s);
            }
        }
    }

    private void printStudentInfo(Student s) {
        System.out.printf("学号: %s, 姓名: %s, 性别: %s, 课程: %s, 成绩: %.1f, 等级: %s%n",
                s.getID(), s.getName(), s.getGender().getLabel(),
                s.getCourse().getLabel(), s.getScore(), s.getGradeLevel());
    }
//heihei
    public static void main(String[] args) {
        Experiment7 exp = new Experiment7();

        try {
            exp.addStudent(new Undergraduate("2023001", "张三", "男", "Java", 99));
            exp.addStudent(new Undergraduate("2023002", "李四", "女", "算法", 72));
            exp.addStudent(new Postgraduate("2024001", "王五", "男", "机器学习", 91));
            exp.addStudent(new Postgraduate("2024002", "赵六", "女", "数据挖掘", 59));

            exp.printUndergraduates();
            System.out.println();
            exp.printPostgraduates();

        } catch (IllegalArgumentException e) {
            System.err.println("输入数据不合法：" + e.getMessage());
        } catch (Exception e) {
            System.err.println("程序运行异常：" + e.getClass().getName() + ": " + e.getMessage());
            e.printStackTrace();
        } finally {
            System.out.println("程序执行完毕。");
        }
    }
}